package com.suixun.util;

import io.jsonwebtoken.Claims;

import java.io.File;
import java.text.SimpleDateFormat;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.RequestContext;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.fileupload.servlet.ServletRequestContext;

public class MediaUploadUtil {
    /*
     * 图片
     */
    public String doImage(String savePath, Integer maxSzie, String[] fileExts,
            HttpServletRequest request, Boolean isvalidate) throws Exception {
        request.setCharacterEncoding("UTF-8");
        RequestContext requestContext = new ServletRequestContext(request);
        String filePath = "";
        Map parameters = new HashMap();
        if (FileUpload.isMultipartContent(requestContext)) {

            DiskFileItemFactory factory =
                    new DiskFileItemFactory(1024 * 1024 * 5, new File(
                            System.getProperty("java.io.tmpdir")));
            // 设置缓冲区大小
            factory.setSizeThreshold(1024 * 1024 * 5);
            // 创建一个文件上传的句柄
            ServletFileUpload upload = new ServletFileUpload(factory);

            // 设置上传文件的整个大小和上传的单个文件大小
            upload.setSizeMax(maxSzie * 10);
            upload.setFileSizeMax(maxSzie);
            try { // 把页面表单中的每一个表单元素解析成一个 FileItem
                List<FileItem> items = upload.parseRequest(request);
                for (FileItem fileItem : items) {
                    // 如果是一个普通的表单元素(type不是file的表单元素)
                    if (fileItem.isFormField()) {
                        String nameString = fileItem.getFieldName();
                        if (isvalidate) {
                            if ("token".equals(nameString)) {
                                try {
                                    JWTHelper jWTHelper = new JWTHelper();
                                    Claims claims = jWTHelper.parseJWT(fileItem.getString());
                                    parameters.put("userid", claims.getId());
                                    parameters.put("usertel", claims.getIssuer());
                                    parameters.put("username", claims.getIssuer());
                                    parameters.put("expiration", claims.getExpiration());
                                    
                                    request.setAttribute("customparameters", parameters);
                                } catch (Exception e) {
                                    throw new Exception("未登录");
                                }
                            }
                            if ("babyid".equals(nameString)) {
                                parameters.put("babyid", fileItem.getString());
                            }
                        }
                    } else { // 获取文件的后缀名
                        String fileName = fileItem.getName();// 得到文件的名字
                        String fileExt =
                                fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
                        if (Arrays.binarySearch(fileExts, fileExt) != -1) {
                            try { // 将文件上传到项目的upload目录并命名，getRealPath可以得到该web项目下包含/upload的绝对路径//
                                fileName = Utils.getNextOrderSn() + "." + fileExt;
                                SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
                                String datestr = format.format(new Date());
                                File descFile =
                                        new File(savePath
                                                + "/pic/" + datestr);
                                if (!descFile.exists()) descFile.mkdirs();
                                fileItem.write(new File(
                                        savePath
                                        + "/pic/"
                                        + datestr
                                        + "/"
                                        + fileName));
                                filePath =
                                        "/pic/" + datestr + "/" + fileName;
                            } catch (Exception e) {
                                throw e;
                            }
                        } else {
                            return "error:ext";
                        }
                    }
                }
            } catch (FileUploadBase.SizeLimitExceededException e) {
                return "error:oversizemax";
            } catch (FileUploadBase.FileSizeLimitExceededException e) {
                return "error:overfilesizemax";
            } catch (FileUploadException e) {
                throw e;
            }
        }
        return filePath;
    }

    /*
     * 录音
     */
    public String doAudio() {
        return "";
    }

    String multipart_form_data = "multipart/form-data";
    String twoHyphens = "--";
    String boundary = "****************fD4fH3gL0hK7aI6"; // 数据分隔符
    String lineEnd = System.getProperty("line.separator");

    /*
     * 上传图片内容，格式请参考HTTP 协议格式。
     * 人人网Photos.upload中的”程序调用“http://wiki.dev.renren.com/wiki/Photos.upload#.
     * E7.A8.8B.E5.BA.8F.E8.B0.83.E7.94.A8 对其格式解释的非常清晰。 格式如下所示： --****************fD4fH3hK7aI6
     * Content-Disposition: form-data; name="upload_file"; filename="apple.jpg" Content-Type:
     * image/jpeg
     * 
     * 这儿是文件的内容，二进制流的形式
     */
    public void addImageContent(Image[] files, DataOutputStream output) {
        for (Image file : files) {
            StringBuilder split = new StringBuilder();
            split.append(twoHyphens + boundary + lineEnd);
            split.append("Content-Disposition: form-data; name=\"" + file.getFormName()
                    + "\"; filename=\"" + file.getFileName() + "\"" + lineEnd);
            split.append("Content-Type: " + file.getContentType() + lineEnd);
            split.append(lineEnd);
            try {
                // 发送图片数据
                output.writeBytes(split.toString());
                output.write(file.getData(), 0, file.getData().length);
                output.writeBytes(lineEnd);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /*
     * 构建表单字段内容，格式请参考HTTP 协议格式（用FireBug可以抓取到相关数据）。(以便上传表单相对应的参数值) 格式如下所示：
     * --****************fD4fH3hK7aI6 Content-Disposition: form-data; name="action" // 一空行，必须有
     * upload
     */
    public void addFormField(Set<Map.Entry<Object, Object>> params, DataOutputStream output) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<Object, Object> param : params) {
            sb.append(twoHyphens + boundary + lineEnd);
            sb.append("Content-Disposition: form-data; name=\"" + param.getKey() + "\"" + lineEnd);
            sb.append(lineEnd);
            sb.append(param.getValue() + lineEnd);
        }
        try {
            output.writeBytes(sb.toString());// 发送表单字段数据
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 直接通过 HTTP 协议提交数据到服务器，实现表单提交功能。
     * 
     * @param actionUrl 上传路径
     * @param params 请求参数key为参数名，value为参数值
     * @param files 上传文件信息
     * @return 返回请求结果
     */
    public String post(String actionUrl, Set<Map.Entry<Object, Object>> params, Image[] files) {
        HttpURLConnection conn = null;
        DataOutputStream output = null;
        BufferedReader input = null;
        try {
            URL url = new URL(actionUrl);
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(120000);
            conn.setDoInput(true); // 允许输入
            conn.setDoOutput(true); // 允许输出
            conn.setUseCaches(false); // 不使用Cache
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "keep-alive");
            conn.setRequestProperty("Content-Type", multipart_form_data + "; boundary=" + boundary);

            conn.connect();
            output = new DataOutputStream(conn.getOutputStream());

            addImageContent(files, output); // 添加图片内容

            addFormField(params, output); // 添加表单字段内容

            output.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);// 数据结束标志
            output.flush();
            // output.close();

            int code = conn.getResponseCode();
            if (code != 200) {
                throw new RuntimeException("请求‘" + actionUrl + "’失败！");
            }

            input = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            StringBuilder response = new StringBuilder();
            String oneLine;
            while ((oneLine = input.readLine()) != null) {
                response.append(oneLine + lineEnd);
            }
            // input.close();

            return response.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 统一释放资源
            try {
                if (output != null) {
                    output.close();
                }
                if (input != null) {
                    input.close();
                }
            } catch (IOException e) {
                throw new RuntimeException(e);
            }

            if (conn != null) {
                conn.disconnect();
            }
        }
    }
}
